#include "bytebuffer.h"

#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")	// includes the compiled WinSock2 code

void ByteBuffer::reset()
{
	m_size = 0;
}

void ByteBuffer::clean()
{
	for(int i = 0; i < m_allocated; ++i)
	{
		m_data[i] = 0;
	}
	m_size = 0;
}

void ByteBuffer::add(const char * const & data)
{
	TemplateVector<unsigned char>::add(strlen(data), (const unsigned char *)data);
}

void ByteBuffer::add(ByteBuffer * a_buffer)
{
	TemplateVector<unsigned char>::addVector(*a_buffer);
}

void ByteBuffer::addBytes(const unsigned char * const & a_bytes, const int & a_numBytes)
{
	TemplateVector<unsigned char>::add(a_numBytes, a_bytes);
}

void ByteBuffer::addByte(const char & value){addBytes((unsigned char *)&value, 1);}
void ByteBuffer::addShort(const short & value){addBytes((unsigned char *)&value, 2);}
void ByteBuffer::addLong(const long & value){addBytes((unsigned char *)&value, 4);}
//void ByteBuffer::addFloat(const long & value){addBytes((unsigned char *)&value, sizeof(float));}
char ByteBuffer::getByte(const int & a_index){return *((char*)&get(a_index));}
short ByteBuffer::getShort(const int & a_index){return *((short*)&get(a_index));}
long ByteBuffer::getLong(const int & a_index){return *((long*)&get(a_index));}

void ByteBuffer::addFloat(const float & value)
{
	float f = value;
	int i = (int)value;
	float difference = f - i;
	if(difference < 0) difference*= -1;
	int count = 0;
	while(difference > .0000000000001 || count == 5)
	{
		f *= 10;
		i = (int)f;
		difference = f - i;
		if(difference < 0) difference *= -1;
		count++;
	}
	long l = (long)f;
	addLong(l);
	addShort(count);
}

float ByteBuffer::getFloat(const int & a_index)
{
	int index = a_index;
	float f = (float)getLong(index); index += sizeof(long);
	for(int i = 0; i < getShort(index); ++i)
		f /= 10;
	return f;
}

void ByteBuffer::set(const char * data)
{
	reset();
	add(data);
}

void ByteBuffer::set(const int a_index, const unsigned char a_value)
{
	TemplateVector<unsigned char>::set(a_index, a_value);
}

const int ByteBuffer::unusedSize()
{
	return (m_allocated - m_size);
}

int ByteBuffer::socket_recv(void * a_socket)
{
	SOCKET socket = (SOCKET)a_socket;
	unsigned long howMuchInBuffer = 0;
	ioctlsocket(socket, FIONREAD, &howMuchInBuffer);
	ensureCapacity(size()+howMuchInBuffer);
	int result = recv(socket, (char*)(&getLast()+1), unusedSize(), 0);
	if(result > 0)
	{
		m_size += result;
	}
	return result;
}

int ByteBuffer::socket_send(void * a_socket)
{
	SOCKET socket = (SOCKET)a_socket;
	int result = send(socket, (const char *)getRawList(), size(), 0);
	if (result != 0 && result != SOCKET_ERROR)
	{
		reset();
	}
	return result;
}

ByteBuffer::~ByteBuffer()
{
	release();
}
